﻿#ifndef _slt_tcpsender_protocol_h_20220718
#define _slt_tcpsender_protocol_h_20220718

#include "SL_asynFramePub.h"
#include "SLT_tool_pub.h"
#include "SL_tcpClient.h"
#include "SLT_tcpSender.h"

class SLTTcpProtocolMemBase : public SLF_sendMemBase
{
public:
	SLTTcpProtocolMemBase(int offset) :m_offset(offset) {}
	virtual char* getData() { return m_mem.get()?m_mem.get() + m_offset : nullptr; }
	virtual uint32_t   getLen() { return (0==m_mem.getLen())?0: m_mem.getLen() - m_offset; }
private:
	virtual void  add(char* _pdata, uint32_t _len) {}
	virtual void resize(uint32_t _len) {}
	int m_offset;
};


/*sender与连接无关。实现消息机制
sender工作机制：
1 sender 被动创建（server端）
	-1）不在map中保存sender。
	-2）由应用层自己缓存使用
	-3）断开不重连
	-4）sender删除，由socket-error事件触发

2 sender 主动创建（客户端）
    -1) 在tcpserver的map中缓存，远端地址相同，复用连接
	-2) 当连接失败后。重新建立连接
	-3）超过3分钟没有通过sender收发数据，怎删除map中的sender
	-4）连接失败状态下发送数据，数据丢弃

3 proxysender： 基于普通sender基础上增加握手协议
	-1）与代理服务tcp连接成功后，发送握手协议
	-2) 接收到握手应答后，才可以正常发送转发数据
*/

class SLT_tcpServerFrameImpl;
class SLT_tcpSenderProtocolImpl :public std::enable_shared_from_this<SLT_tcpSenderProtocolImpl>, public SLT_TCPSender,
								public SLTcpClientCB, public SLT_memLeakCheck<SLT_tcpSenderProtocolImpl>
{
public:
	enum _sender_work_mode
	{
		_sender_work_mode_cli,   //客户端模式
		_sender_work_mode_ser    //服务器模式
	};
	enum _sender_work_state
	{
		_sender_work_state_init,
		_sender_work_state_conning,
		_sender_work_state_handshaking,  //代理握手中
		_sender_work_state_ok,
		_sender_work_state_stop
	};
	SLT_tcpSenderProtocolImpl( SLT_tcpServerFrameImpl *_pser);
	virtual ~SLT_tcpSenderProtocolImpl(){}

	void    connect(SLTcpClientPtr &_client,const std::string &_rip,int _rport);   //主动连接，客户端
	void    recvConnect(SLTcpClientPtr& _cliPtr);          //被动接收，服务端
	SLT_TCPSenderPtr getSenderApt();
	
	virtual bool SLF_postMsg(uint32_t _SessID, int msgid, uint32_t _srcID,const SLF_sendMemBasePtr& _data);

	virtual void TcpClient_onConnect(tcp_error_type _errType);
	virtual void TcpClient_onRecv(char* _pdata, int _len);
	virtual void TcpClient_onSend() {}
	virtual void TcpClient_onError(tcp_error_type _type);

	void  _closeSender();

	void  checkState();
	virtual std::string getKey();
	virtual void connectSuccNotify() {}
	virtual int recvSplitCmd();
	
	_sender_work_state  m_workState = _sender_work_state_init;
	_sender_work_mode  m_workMode = _sender_work_mode_ser;

	std::mutex    m_tcpClientLock;
	SLTcpClientPtr m_tcpClient;
	std::atomic<uint64_t>   m_lastConnectTime{ 0 };//最后处理数据的时间
	int           m_reconnectDiffTime = -1; //tcp  重连间隔
	
	SLT_memBuf m_precvAllMem;

	uint32_t m_rip;
	std::string m_rStrIp;
	uint16_t m_rport;
	SLT_tcpServerFrameImpl  *m_tcpServer = nullptr;
	//uint32_t  m_sid = 0;   //处理命令的sessionid

	uint32_t m_id = 0;
	std::atomic<uint64_t>   m_lastDataTime;//最后处理数据的时间.  废弃。共享sender通过超时回收机制废弃。当没有人持有sender时立即释放

	void addref() { m_usernum++;}
	void delref();
	std::atomic<uint32_t>   m_usernum{0};  //引用计数. 当引用计数为0，客户端类型：执行删除

	static SLT_tcpRecvMsgCb_type  m_precvMsgCBFun;
};
typedef std::shared_ptr< SLT_tcpSenderProtocolImpl> SLT_tcpSenderProtocolImplSptr;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class SLT_TCPProxyTransSenderImpl :public SLT_tcpSenderProtocolImpl
{
	//代理传输sender
	struct _Head_prefix
	{
		int no_pref1 = 0, no_pref2 = 0, no_pref3 = 0, dev_no = 0, dev_sub_no = 0;
		AIGC_JSON_HELPER(no_pref1, no_pref2, no_pref3, dev_no, dev_sub_no)
	};
	struct CProxyProHandshake  //转发通道握手请求
	{
		int ht_timeout_ms = 0;   //小于等于0 表示不计算超时断开
		std::string name;
		_Head_prefix remote_agent_v2v_number;
		std::string svr_id;
		std::string sessionid;
		int encrypt = 0;
		AIGC_JSON_HELPER(ht_timeout_ms, name, remote_agent_v2v_number, svr_id, sessionid, encrypt)
	};
	struct CProxyProHandshake_resp  //转发通道握手应答
	{
		int   ret;
		std::string  sessionid;
		std::string  ret_msg;
		AIGC_JSON_HELPER(ret, sessionid, ret_msg)
	};

public:
	SLT_TCPProxyTransSenderImpl( SLT_tcpServerFrameImpl* _pser)
		:SLT_tcpSenderProtocolImpl(_pser){}

	void    setProxyInfo(int _prefix1, int _prefix2, int _prefix3,int _devno,int _subno,const std::string &_svrid, int _encrypt,int _timeout_ms) {
		m_prefix1 = _prefix1; m_prefix2 = _prefix2; m_prefix3 = _prefix3; m_encrypt = _encrypt;
		m_devno = _devno;m_subno = _subno;
		m_svrid = _svrid;
		m_timeout_ms = _timeout_ms;
	}
	virtual std::string getKey();
	virtual void connectSuccNotify();
	virtual int recvSplitCmd();

	SLT_elapseTimer  m_handsharkeTimer;  //握手开始时间，超过1s，断开连接
	int  m_prefix1 = 0, m_prefix2 = 0, m_prefix3 = 0, m_devno = 0, m_subno = 0;
 	int  m_encrypt = 0;
	std::string  m_svrid;
	int  m_timeout_ms = 15000;
};
typedef std::shared_ptr< SLT_TCPProxyTransSenderImpl> SLT_TCPProxyTransSenderImplSptr;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//接口sender
// 每个申请sender 动作，分配一个新的适配对象，指向真正的sender
//通过引用计数管理真实sender声明周期
class SLT_tcpSenderProtocolApt : public SLT_TCPSender
{
public:
	SLT_tcpSenderProtocolApt(SLT_tcpSenderProtocolImplSptr psender) :m_pender(psender)
	{
		m_pender->addref();
	};
	~SLT_tcpSenderProtocolApt() {
		m_pender->delref();
		m_pender.reset();
	}
	virtual bool SLF_postMsg(uint32_t _SessID, int msgid, uint32_t _srcID, const SLF_sendMemBasePtr& _data)
	{
		return m_pender->SLF_postMsg(_SessID, msgid, _srcID, _data);
	}
	SLT_tcpSenderProtocolImplSptr m_pender;
};
typedef std::shared_ptr<SLT_tcpSenderProtocolApt>  SLT_tcpSenderProtocolAptSptr;

#endif